#ifndef _TALK_SESSION_STR_STRSTRCALL2_H_
#define _TALK_SESSION_STR_STRSTRCALL2_H_

#include "talk/p2p/base/session.h"
#include "talk/p2p/base/transportchannel.h"
#include "talk/p2p/base/p2ptransportchannel.h"

#include "talk/examples/crossfirewall/cfcommon.h"
#include "talk/examples/crossfirewall/cfsessionclient.h"

namespace cricket {

	enum StrCallMsg{
		STR_CALL_STATE,
		STR_CALL_DATA_INCOMING
	};

	struct DataHeader{
		unsigned char  ex;
		unsigned char  ttype;
		unsigned short len;
	};

	struct CFSession{
		Session* session_;
		std::string channel_name_;
		CFSession(Session* session, std::string channel_name): session_(session), channel_name_(channel_name) {}
	};

	struct CFTransportChannel{
		TransportChannel* channel_;
		int pack_recv_;
		int pack_send_;
		int data_recv_;
		int data_send_;

		int pack_recv_ts_;
		int pack_send_ts_;
		int data_recv_ts_;
		int data_send_ts_;

		CFTransportChannel(TransportChannel* channel): channel_(channel), 
			pack_recv_(0), pack_send_(0), data_recv_(0), data_send_(0),
		    pack_recv_ts_(0), pack_send_ts_(0), data_recv_ts_(0), data_send_ts_(0) {}
	};

	class CFSessionClient;

	class CFCall : public sigslot::has_slots<>
	{
	public:
		CFCall(std::string local_jid, std::string remote_jid, CFSessionClient* cfsession_client);
		~CFCall();

		void MakeCall();
		void HangUpCall();
		int  SendPacket(int ttype, const char* data, size_t len);

		void OnSessionIncoming(Session* session);
		void OnSessionDestroy(Session* session);

	private:
		void ChangeCallState(int state);
		void ChangeCallState(int p2p_enable, int upnp_enable);
		void OnCallAllocatorPhaseChange(const std::string& channel_name, int phase);

		void InitiateSession(const std::string& session_type, const std::string& channel_name);
		void TerminateSession(Session *session);

		void AcceptSession(Session* session, bool bsent, std::string channel_name);
		void RejectSession(Session* session);
		void AddSession();

		void OnSessionState(BaseSession* session, Session::State state);
		void OnSessionError(BaseSession *session, Session::Error error);

		void OnP2PChannelWritableState(TransportChannel* channel);
		void OnPacketIncoming(int ttype, const char* data, size_t len);
		void OnP2PChannelReadPacket(TransportChannel* channel, const char* data, size_t len);

	public:
		sigslot::signal3<CFCall*, std::string, int> SignalCallStateChange;

	private:
		int state_;
		bool p2p_enable_, upnp_enable_;
		int session_num_;
		std::string local_jid_;
		std::string remote_jid_;
		CFSessionClient* cfsession_client_;

		std::vector<CFSession> sessions_;
		std::vector<CFTransportChannel> channels_;

		talk_base::Thread *worker_thread_;

		talk_base::CriticalSection state_crit_;
		talk_base::CriticalSection vector_crit_;
		talk_base::CriticalSection p2ps_crit_;
		
		char* data_;
		int   data_seq_;
		int   datahead_size_;

		int   time_now_;

		std::map<std::string, int> channels_phase_;
	};
}

#endif